package com.sumainfor.zuul.aspect;

import com.google.gson.Gson;
import com.sumainfor.common.annotation.SysLog;
import com.sumainfor.common.util.IPUtils;
import com.sumainfor.common.util.JsonResult;
import com.sumainfor.common.util.R;
import com.sumainfor.common.util.UUIDUtils;
import com.sumainfor.zuul.entity.SysLogEntity;
import com.sumainfor.zuul.entity.SysUserEntity;
import com.sumainfor.zuul.service.SysLogService;
import com.sumainfor.zuul.util.HttpContextUtils;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.Period;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;


/**
 * 系统日志，切面处理类
 */
@Aspect
@Component
public class SysLogAspect {
    @Autowired
    private SysLogService sysLogService;

    @Pointcut("@annotation(com.sumainfor.common.annotation.SysLog)")
    public void logPointCut() {

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) {
        RuntimeException exception = null;
        DateTime start = new DateTime();
        //执行方法
        Object result = null;
        try {
            result = point.proceed();
        } catch (Throwable throwable) {
            exception = new RuntimeException(throwable);
        }

        DateTime end = new DateTime();

        Interval interval = new Interval(start, end);
        Period period = interval.toPeriod();
        //执行时长(毫秒)
        String time = period.getMillis() + " 毫秒";
        //成功才去记录
        if (result instanceof JsonResult) {
            if (!((JsonResult) result).isSuccess()) {
                return result;
            }
        } else if (result instanceof R) {
            if (((Integer) (((R) result).get("code"))) != 0) {
                return result;
            }
        }
        //保存日志
        saveSysLog(point, time, exception);

        return result;
    }

    private void saveSysLog(ProceedingJoinPoint joinPoint, String time, RuntimeException exception) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        SysLogEntity sysLog = new SysLogEntity();
        SysLog syslog = method.getAnnotation(SysLog.class);
        if (syslog != null) {
            //注解上的描述
            sysLog.setTitle(syslog.value());
            sysLog.setType(Integer.parseInt(syslog.type()));
        }
        sysLog.setLogId(UUIDUtils.generatePrefixUuid("SYS_LOG"));
        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");

        //请求的参数
        Object[] args = joinPoint.getArgs();
        try {
            String params = new Gson().toJson(args[0]);
            sysLog.setParams(params);
        } catch (Exception e) {

        }

        //获取request
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        //设置IP地址
        sysLog.setRemoteAddr(IPUtils.getIpAddr(request));
        sysLog.setRequestUri(request.getServletPath());
        //用户名
        SysUserEntity userEntity = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal());
        if (userEntity != null) {
            Integer userId = userEntity.getUserId();
            sysLog.setInsby(String.valueOf(userId));
            sysLog.setDeptid(userEntity.getDeptId() + "");
        }
        sysLog.setInstm(new Date());


        sysLog.setTime(time);

        if (exception != null) {
            sysLog.setException(exception.getMessage());
        }

        //保存系统日志
        sysLogService.insert(sysLog);

        if (exception != null) {
            throw exception;
        }
    }
}
